#    MythMobile, a Django interface to MythTV for mobile devices
#    Copyright (C) 2011 Andrew Wilkinson (andrewjwilkinson@gmail.com)
#
#     This program is free software; you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation; either version 2 of the License, or
#     (at your option) any later version.
#
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License along
#     with this program; if not, write to the Free Software Foundation, Inc.,
#     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from datetime import datetime, timedelta
import logging
import os
import threading
import time

from asyncproc import Process

from connection import Connection
import detect_encoder
from segmenter import Segmenter

import settings

class LiveTVProcessor(threading.Thread):
    def __init__(self, *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)

        format, self.channel_no = kwargs["args"]

        self.dir_name = settings.DATA_DIR + os.sep + "line-%s-%s" % (format, self.channel_no) + os.sep + "line-%s-%s" % (format, self.channel_no)
        try:
            os.makedirs(self.dir_name)
        except OSError, exc:
            if exc.errno == 17: # File exists
                logging.warn("Failed to create directory %s, it already exists." % (self.dir_name, ))
            else:
                raise

        self.segmenter = Segmenter(self.dir_name, self.segmenter_stop)
        self.kill = False
        self.timer_expires = datetime.now() + timedelta(seconds=60)

    def __del__(self):
        self.segmenter.delete_files()

        os.rmdir(self.dir_name)

    def run(self):
        c = Connection()
        c.ann()
        recorder_id = c.get_next_free_recorder()
        chain_id = c.get_chain_id()
        c.query_recorder_spawn_livetv(recorder_id, chain_id, False, self.channel_no)
        c.backend_message_livetv_chain_update(chain_id)
        c.backend_message_recordinglist_change_add(self.channel_no)
        while not c.query_recorder_is_recording(recorder_id):
            time.sleep(1)

        stable_count = 0
        file_name = ""
        while stable_count < 5:
            new_file_name = c.query_recorder_get_current_recording(recorder_id)[8]

            if new_file_name == file_name:
                stable_count += 1
                time.sleep(1)
            else:
                file_name = new_file_name
                stable_count = 0

        data_conn = Connection()
        socket_id = data_conn.ann_filetransfer("/" + file_name.split("/")[-1])

        #encoder = Process("mencoder - -o - -vf scale=480:-10,harddup -oac faac -faacopts mpeg=4:object=2:raw:br=128 -of lavf -lavfopts format=mpegts -ovc x264 -x264encopts bitrate=600:nocabac:level_idc=30:bframes=0:profile=baseline".split(" "),
            #stderr=None)
        encoder = Process((detect_encoder.iphone_encoder % ("-", "-")).split(" "), stderr=None)

        buf_size = 64*1024
        unread = 0
        processed = ""
        while not self.kill and datetime.now() < self.timer_expires:
            sent_size = int(c.query_filetransfer(socket_id, c.REQUEST_BLOCK, buf_size)[0])
            if sent_size == 0:
                continue
            assert sent_size > 0

            data = data_conn.read(int(sent_size) + unread)
            unread = (int(sent_size) + unread) - len(data)
            assert unread >= 0, (sent_size, data, unread)

            if encoder.exitstatus() is not None:
                logging.error("Encoder exited with a status of %s", encoder.exitstatus())
                break
            encoder.write(data)
            encdata = encoder.read()
            processed += encdata

            while len(processed) > 4096:
                self.segmenter.add_packet(processed[:4096])
                processed = processed[4096:]

            if sent_size < buf_size:
                buf_size = max(buf_size - 16*1024, 16*1024)
            else:
                buf_size = min(buf_size + 16*1024, 256*1024)

        logging.debug("LiveTVProcessor exiting.")

    def reset_timer(self):
        #self.timer_expires = datetime.now() + timedelta(seconds=60)
        pass

    def segmenter_stop(self):
        self.kill = True
